# 类与对象

# 日期类进行举例
# class Date:
#     def __init__(self, year=1949, month=10, day=1):  # 构造方法
#         # 成员变量
#         self.year = year
#         self.month = month
#         self.day = day
#
#     def Print(self):  # 成员方法
#         print(self.year, self.month, self.day, sep="-")


# a = Date()  # 全缺省，此对象属性为默认的1949-10-1 实例化对象
# b = Date(2022, 8, 29)
# a.Print()
# b.Print()
# class Date:
#     def __init__(self, year=1949, month=10, day=1):  # 构造方法
#         # 成员变量
#         self.year = year
#         self.month = month
#         self.day = day
#
#     def Print(self, week):  # 成员方法
#         print(self.year, self.month, self.day, week, sep="-")


# a = Date(2022, 8, 29)
# a.week = "星期一"  # 添加str类型的属性
# a.Print(a.week)
# a.day = 28  # 或者修改里面的成员变量
# a.week = "星期天"
# a.Print(a.week)

# class Date:
#     def __init__(self, year=1949, month=10, day=1):  # 构造方法
#         # 成员变量
#         self.year = year
#         self.month = month
#         self.day = day
#
#     def __del__(self):
#         print("析构方法")
#
#     def Print(self):  # 成员方法
#         print(self.year, self.month, self.day, sep="-")
#
#
# a = Date(2022, 8, 29)
# a.Print()  # 调用成员方法
# # 程序结束自动调用析构方法

# class Test:
#     num = 0  # 类属性
#
#     # def enjoy():
#     #     print("普通的方法")
#
#     def Print(self, *args):  # *args 为可变参数 表示多余的参数就可存在于此
#         print("年龄为{}，编号为{}".format(self.age, Test.num))
#
#
# t1 = Test()
# t1.age = 19  # 新增一个成员属性  没有就报错
# t1.Print()
# Test.num = 2
# t2 = Test()
# t2.age = 20
# t2.Print()
# class Test:
#     num = 1
#
#     def Print(self):
#         print("这里是成员方法")
#
#     @classmethod  # 类方法
#     def test(cls):
#         print("这里是类方法,编号为{}".format(cls.num))  # cls表示当前类  只能表示类属性 成员属性就不行了
#
#
# t = Test()
# t.Print()  # 实例对象调用实例方法 -- 成员方法
# t.test()  # 对象调用类方法
# Test.test()  # 直接通过类名进行调用类方法

# 类的继承
# class Animal:
#     def __init__(self):
#         print("父类的构造方法")
#
#     def show(self):
#         print("父类的成员方法")
#
#     @classmethod
#     def test1(cls):
#         print("父类的类方法")
#
#     @staticmethod
#     def test2():
#         print("父类的静态方法")
#
#
# class Cat(Animal):  # 继承动物类
#     def __init__(self):
#         super().__init__()
#         print("子类的构造方法")
#
#     def test(self):
#         print("子类的成员方法")
#
#
# c = Cat()
# c.test()
# c.show()  # 父类的成员方法
# c.test2()  # 父类的静态方法
# c.test1()  # 父类的类方法

# 利用__表示私有成员，实现类的封装
# class Employee:
#     def __init__(self, name="张三", department="computer", age=18):
#         self.__name = None
#         self.__department = None
#         self.__age = None
#
#         self.setName(name)
#         self.setDepartment(department)
#         self.setAge(age)
#
#     def setName(self, name):
#         if type(name) != str:
#             print("输入的名字必须是字符")
#             return
#         self.__name = name  # 给私有成员
#
#     def setDepartment(self, department):
#         if department not in ["computer", "math", "chinese"]:
#             print("必须在computer, math, chinese这三者里面去选")
#             return
#         self.__department = department
#
#     def setAge(self, age):
#         if type(age) != int or age < 18 or age > 24:
#             print("输入的年龄信息不对哦")
#             return
#         self.__age = age
#
#     def show(self):
#         print("姓名:{:3} 专业:{:8} 年龄:{:2} ".
#               format(self.__name, self.__department, self.__age))
#
#
# class ProjectManager(Employee):  # 继承父类
#     def __init__(self, name="张三", department="computer", age=18, title="middle"):
#         # Employee.__init__(self, name, department, age)  # 调用父类的构造方法
#         super().__init__(name, department, age)
#         self.__title = None
#         self.setTitle(title)
#
#     def setTitle(self, title):
#         if type(title) != str:
#             print("这里需要填的是职称哦")
#             return
#         self.__title = title
#
#     def show(self):  # 方法重写，相同方法名和参数列表
#         # Employee.show(self)
#         super().show()
#         print("职称:{}".format(self.__title))
#
#
# a = Employee()
# a.show()
# e = ProjectManager()
# e.show()

# Python的多继承
# class Phone:
#     def receive(self):
#         print("接电话")
#
#     def send(self):
#         print("打电话")
#
#
# class Message:
#     def reveiveMsg(self):
#         print("接受短信")
#
#     def sendMsg(self):
#         print("发送短信")
#
#
# class Mobile(Phone, Message):  # 多继承，继承两个父类
#     pass  # 空语句
#
#
# m = Mobile()
# m.receive()
# m.send()
# m.reveiveMsg()
# m.sendMsg()

# 类的多态
# class Animal:
#     def __init__(self, name):
#         self.name = name
#
#     def enjoy(self):
#         print(self.name + "此为动物行为")
#
#
# class Cat(Animal):
#     def enjoy(self):
#         print(self.name + "喵喵~")  # 注意此name不能是私有属性哦，因为父类的私有属性子类是继承不了的
#
#
# class Dog(Animal):
#     def enjoy(self):
#         print(self.name + "汪汪~")
#
#
# class Person:
#     def __init__(self, name, _id):
#         self.__name = name
#         self.__id = _id
#
#     def drive(self, ani: Animal):
#         ani.enjoy()
#
#
# c = Cat("猫猫")
# d = Dog("狗狗")
# c.enjoy()
# d.enjoy()
# p = Person("管理员", 114)
# p.drive(c)
# p.drive(d)

# 运算符重载
# 列表和数字的相加减
# class Computing:
#     def __init__(self, value: list):
#         self.value = value
#
#     def __add__(self, other):  # +的运算符重载，第一个self对象本身为+左边的参数，other就是对应的右边的参数
#         if type(other) != int and type(other) != float:
#             print("输入的不是一个数字哦")
#             return
#         lst = []
#         for i in self.value:
#             lst.append(i + other)
#         return lst
#
#     def __sub__(self, other):  # -的运算符重载
#         if type(other) != int and type(other) != float:
#             print("输入的不是一个数字哦")
#             return
#         lst = []
#         for i in self.value:
#             lst.append(i - other)
#         return lst
#
#
# c = Computing([1, 2, 3, 4, 5])
# print(c + 1)
# print(c - 1)

# 重载__str__ 和 __ge__ 一个是方便转化为字符串(print和str()会调用重载的str方法，repr可以在多种操作下转化为自定义的字符串模式) 另一个是重载大于等于
# class Students:
#     def __init__(self, name="张三", age=18):
#         self.name = name
#         self.age = age
#
#     def __str__(self):
#         return "{} {}".format(self.name, self.age)
#
#     def __repr__(self):
#         return "{} {}".format(self.name, self.age)
#
#     def __ge__(self, obj):
#         if self.age >= obj.age:
#             return True
#         return False
#
#
# s = Students("李四", 20)
# e = Students()
# if e >= s:
#     print(e)
# else:
#     print(s)
# a = e.__repr__()
# print(a)
# print(type(a))

# 重载 getitem 返回对应可迭代对象的切片值 setitem 给对应可迭代对象切片对应的赋值 delitem 删除对应索引或者切片的值
# class ListDate:
#     def __init__(self, data: list):
#         self.data = data[:]  # 将data列表拷贝一份给此对象属性
#         # self.data = data  # 传的是对象的引用 那么和原本的列表没有区别了，此类对象进行改变原本的列表也会发生改变
#
#     def __getitem__(self, item):
#         return self.data[item]
#
#     def __setitem__(self, key, value):
#         self.data[key] = value
#
#     def __delitem__(self, key):
#         del self.data[key]
#
#
# lst = [2, 3, "123"]
# s = ListDate(lst)
# print(s[2])  # 123
# print(s[:2])  # 2 3
# s[2] = 4
# print(s[2])
# del s[0]
# for i in s:
#     print(i, end=" ")
# print()
# print(lst)

# 面向对象编程的应用:
# 学生信息管理程序:
# class Student:
#     __n = 0  # 类属性，统计构造学生对象的个数
#     __lst = ["C++", "Python", "Java"]  # 储存科目的地方 类属性
#
#     def __init__(self, Id: int, name: str, course: str):
#         Student.__n += 1
#         self.__id = 0
#         self.__name = "初始"
#         self.__course = "无"
#         if self.setId(Id) and self.setName(name) and self.setCourse(course):
#             pass
#         else:
#             print("第{}输入的学生存在问题,注意检查，防止程序报错".format(Student.__n))
#
#     def __repr__(self):
#         return "{:<3} {:<4} {:<6}".format(self.__id, self.__name, self.__course)
#
#     def setId(self, Id):
#         if type(Id) == int:
#             self.__id = Id
#             return True
#         return False
#
#     def setName(self, name):
#         if type(name) == str:
#             self.__name = name
#             return True
#         return False
#
#     def setCourse(self, course):
#         if course in Student.__lst:
#             self.__course = course
#             return True
#         return False
#
#     def getId(self):
#         return self.__id
#
#     def getName(self):
#         return self.__name
#
#     def getCourse(self):
#         return self.__course


# s1 = Student(1, "张三", "C++")
# s2 = Student(2, "张四", "Java")
# s3 = Student(3, "张五", "Python")
# s4 = Student(4, "小刘", "C++")
# # s5 = Student(5, "dw", "C")
# # print(s1)
# # print(s2)
# # print(s3)
# # print(s4)
# print("--------遍历原始数据----------")
# lst = [s1, s2, s3, s4]
# for i in lst:
#     print(i)
# print("--------追加数据后进行遍历----------")
# s5 = Student(5, "王五", "Java")
# lst.append(s5)
# for i in lst:
#     print(i)
# print("--------修改数据后进行遍历----------")
# s3.setId(10)
# for i in lst:
#     print(i)
# print("--------排序数据后后进行遍历----------")
# lst.sort(key=lambda x: x.getId())
# for i in lst:
#     print(i)
# print("--------删除数据后后进行遍历----------")
# del lst[2]  # 小刘
# for i in lst:
#     print(i)

# print(isinstance("4", (int, float)))
# date = [1, 2, 3, 4]
# date = [item + 1 for item in date]
# print(date)

# print(list(zip([1, 2, 4], [3, 4, 6])))
# n = 1
# i = n if n == 2 else 2
# print(i)
# raise Exception()  # 抛异常？

# 编程题:
# 计算班级总分和平均分
# class Group:
#     total = 0
#     count = 0
#
#     def __init__(self):
#         self.score = None
#
#     def setScore(self, score: int):
#         if not isinstance(score, int) or (score < 0 or score > 100):
#             print("输入成绩错误")
#             return
#         self.score = score
#         Group.count += 1
#         self.sum()
#
#     def sum(self):
#         Group.total += self.score
#
#     @classmethod
#     def average(cls):
#         return cls.total / cls.count
#
#
# lst = eval(input("请输入全班所有人的成绩列表:"))
# while not isinstance(lst, list):
#     lst = eval(input("请输入全班所有人的成绩列表:"))
# g = Group()
# for i in lst:
#     g.setScore(i)
# print("总分为{},平均分为{}".format(Group.total, g.average()))

# 二次方程式
# import math
#
#
# class Equation:
#     def __init__(self, a, b, c):
#         if type(a) != int or type(b) != int or type(c) != int:
#             print("输入整型")
#             return
#         self.a = a
#         self.b = b
#         self.c = c
#
#     def getDiscriminant(self):
#         return self.b ** 2 - 4 * self.a * self.c
#
#     def getRoot1(self):
#         sm = self.getDiscriminant()
#         if sm < 0:
#             return 0
#         return (-self.b + math.sqrt(sm)) / (2 * self.a)
#
#     def getRoot2(self):
#         sm = self.getDiscriminant()
#         if sm < 0:
#             return 0
#         return (-self.b - math.sqrt(sm)) / (2 * self.a)
#
#
# e = Equation(1, 4, 2)
# print("两个根分别为{}和{}".format(e.getRoot1(), e.getRoot2()))

# 设计一个描述自由落体的运动的类：
# class FreeFall:
#     g = 9.8
#
#     def speed(self, s):
#         return FreeFall.g * s
#
#     def displacement(self, s):
#         return 0.5 * FreeFall.g * s * s
#
#
# f = FreeFall()
# print(f.speed(3))
# print(f.displacement(3))